﻿using System.Collections.Generic;
using System.Threading.Tasks;
using SaiLing.Domain;
using SaiLing.Domain.Specification;
using SaiLing.Exceptions;
using SaiLing.SingleSignOn.Application.Service.Interfaces.System;
using SaiLing.SingleSignOn.Domain.Entities.DataTransferObject;
using SaiLing.SingleSignOn.Domain.Entities.System;
using SaiLing.SingleSignOn.Domain.Interfaces.System;
using SaiLing.Paging;
using SaiLing.SingleSignOn.Domain.Specifications.System;
using System.Linq;
using System;

namespace SaiLing.SingleSignOn.Application.Service.Providers.System
{
    public class ModuleService : BaseService<Module>, IModuleService
    {
        private IModuleActionRepository Moduleactionrepository { get; set; }
        private IModuleRepository ModuleRepository { get; set; }

        public ModuleService(IUnitOfWork unitOfWork, IModuleRepository repository, IModuleActionRepository moduleactionrepository) : base(unitOfWork, repository)
        {
            Moduleactionrepository = moduleactionrepository;
            ModuleRepository = repository;
        }

        public  Task Create(Module entity, LogUser logUser)
        {
            var isExist = ExistsAsync(new DirectSpecification<Module>(x => x.LogicRemove == false && x.Name == entity.Name && x.ParentId == entity.ParentId));
            if (isExist.Result)
                throw new SaiLingException("该模块已经存在!");

             Add(entity);
            
            return ServiceFactory.LogService.LogAsync("添加功能模块", $"模块名称:{entity.Name}", logUser);
        }

        public Task<PageData<ModuleDTO>> PageList(int pageIndex, int pageSize, string name,Guid appid)
        {
            var spec = new ModuleSpecification(name, appid);
            return ModuleRepository.PageDataList(pageIndex, pageSize, spec, x => x.CreateTime, true);
           
        }

        public Task<IEnumerable<Module>> List(string name,Guid appid)
        {
            var spec = new ModuleSpecification(name, appid);
            return Task.FromResult(GetMany(spec));
        }

        public async Task<int> Edit(Module entity)
        {
            if (await ExistsAsync(new DirectSpecification<Module>(x => x.Id != entity.Id && x.Name == entity.Name && x.AppId != entity.AppId)))
                throw new SaiLingException("菜单名重复");

            if (entity.Actions != null && entity.Actions.Any())
            {
                entity.Actions.ForEach(x =>
                {
                    x.ModuleId = entity.Id;
                });
            }
            var newActions = entity.Actions != null ? entity.Actions.ToList() : new List<ModuleAction>();
            var oldActions =
                Moduleactionrepository.GetMany(new DirectSpecification<ModuleAction>(x => x.ModuleId == entity.Id)).ToList();
            var addList = newActions.Except(oldActions, new ModuleActionEqualityComparer());
            var delList = oldActions.Except(newActions, new ModuleActionEqualityComparer());
            var updateList = newActions.Intersect(oldActions, new ModuleActionEqualityComparer());
            Update(entity, x => x.Area, x => x.ExecAction, x => x.ExecController, x => x.Icon, x => x.Name, x => x.ParentId, x => x.Sort, x => x.Visible);
            foreach (var item in addList)
            {
                await Moduleactionrepository.Add(item);
            }
            foreach (var item in updateList)
            {
                Moduleactionrepository.Modify(item);
            }
            foreach (var item in delList)
            {
                var temp = await Moduleactionrepository.GetByKey(item.Id);
                Moduleactionrepository.Remove(temp);
            }

            return await SaveChangesAsync();
        }

        public async Task<int> Delete(Module[] entityies)
        {
            var ids = entityies.Select(x => x.Id).ToList();
            await LogicRemove(new DirectSpecification<Module>(x => ids.Contains(x.Id)));
            return await SaveChangesAsync();
        }

        public List<Module> GetAllModuleByAction(List<Guid> lstActionId)
        {
            var allModuleActions = Moduleactionrepository.GetAll().Where(x => !x.LogicRemove).ToList();
            List<Guid> lstModuleId = new List<Guid>();
            lstActionId.ForEach(x =>
            {
                var moduleId = allModuleActions.Where(y => y.Id == x).Select(y => y.ModuleId).FirstOrDefault();
                if (moduleId != null)
                {
                    lstModuleId.Add(moduleId);
                    allModuleActions.RemoveAll(j => j.ModuleId == moduleId);
                }
            });
            return GetAllModuleByModuleId(lstModuleId);
        }

        /// <summary>
        /// 根据模块id获取树形菜单
        /// </summary>
        /// <param name="lstModuleId"></param>
        /// <param name="lstResult"></param>
        /// <returns></returns>
        private List<Module> GetAllModuleByModuleId(List<Guid> lstModuleId, List<Module> lstResult = null, List<Module> allMenu = null)
        {
            //获取所有菜单
            if (allMenu == null)
                allMenu = GetAll().Where(x => !x.LogicRemove).ToList();
            if (lstResult == null) lstResult = new List<Module>();
            lstModuleId.ForEach(x =>
            {
                var menu = allMenu.Where(y => y.Id == x).FirstOrDefault();
                if (menu != null)
                {
                    lstResult.Add(menu);
                    allMenu.Remove(menu);
                    GetAllModuleByModuleId(new List<Guid> { menu.ParentId }, lstResult, allMenu);
                }
            });
            return lstResult;
        }
    }
}
